/*
 * Powered By dico
 * Since 2017 - 2018
 */package com.seeyoui.kensite.bussiness.exam.exercise.service;
 
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.seeyoui.kensite.bussiness.exam.common.Const;
import com.seeyoui.kensite.bussiness.exam.common.Method;
import com.seeyoui.kensite.bussiness.exam.exercise.domain.Exercise;
import com.seeyoui.kensite.bussiness.exam.exercise.persistence.ExerciseMapper;
import com.seeyoui.kensite.bussiness.exam.question.domain.Question;
import com.seeyoui.kensite.bussiness.exam.question.domain.QuestionVO;
import com.seeyoui.kensite.bussiness.exam.question.service.QuestionService;
import com.seeyoui.kensite.bussiness.exam.questionOption.domain.QuestionOption;
import com.seeyoui.kensite.bussiness.exam.questionOption.persistence.QuestionOptionMapper;
import com.seeyoui.kensite.common.base.service.BaseService;
import com.seeyoui.kensite.common.exception.CRUDException;

/**
 * Exercise
 * @author dico
 * @version 2.0
 * @since 1.0
 * @date 2018-01-08
 */

@Service
public class ExerciseService extends BaseService {
	
	@Autowired
	private ExerciseMapper exerciseMapper;
	@Autowired
	private QuestionService questionService;
	@Autowired
	private QuestionOptionMapper questionOptionMapper;

	/**
	 * 根据ID查询单条数据
	 * @param id
	 * @return
	 * @throws CRUDException
	 */
	public Exercise findOne(String id) throws CRUDException{
		return exerciseMapper.findOne(id);
	}
	
	/**
	 * 查询数据集合
	 * @param exercise
	 * @return
	 * @throws CRUDException
	 */
	public List<Exercise> findList(Exercise exercise) throws CRUDException {
		return exerciseMapper.findList(exercise);
	}
	
	/**
	 * 查询所有数据集合
	 * @param exercise
	 * @return
	 * @throws CRUDException
	 */
	public List<Exercise> findAll(Exercise exercise) throws CRUDException {
		return exerciseMapper.findAll(exercise);
	}
	
	/**
	 * 查询数据总数
	 * @param exercise
	 * @return
	 * @throws CRUDException
	 */
	public int findTotal(Exercise exercise) throws CRUDException {
		return exerciseMapper.findTotal(exercise);
	}
	
	/**
	 * 查询数据总数排除当前数据
	 * @param exercise
	 * @return
	 * @throws CRUDException
	 */
	public int findExTotal(Exercise exercise) throws CRUDException {
		return exerciseMapper.findExTotal(exercise);
	}
	
	/**
	 * 数据新增
	 * @param exercise
	 * @throws CRUDException
	 */
	public void save(Exercise exercise) throws CRUDException{
		exercise.preInsert();
		exerciseMapper.save(exercise);
	}
	
	/**
	 * 数据修改
	 * @param exercise
	 * @throws CRUDException
	 */
	public void update(Exercise exercise) throws CRUDException{
		exercise.preUpdate();
		exerciseMapper.update(exercise);			
	}
	
	/**
	 * 数据删除
	 * @param listId
	 * @throws CRUDException
	 */
	public void delete(List<String> listId) throws CRUDException {
		exerciseMapper.delete(listId);
	}
	
	/**
	 * 数据假删除
	 * @param exercise
	 * @throws CRUDException
	 */
	public void remove(Exercise exercise) throws CRUDException{
		exercise.preUpdate();
		exerciseMapper.remove(exercise);			
	}
	
	/**
	 * 创建一个练习
	 * @param userId
	 * @param libraryId
	 * @param single
	 * @param multiple
	 * @param judge
	 * @param duration
	 * @return
	 * @throws CRUDException
	 */
	public Exercise create(String userId, String libraryId, int single, int multiple,
			int judge, int duration) throws CRUDException{
		Exercise exercise = new Exercise();
		exercise.setTotalScore(String.valueOf(single + multiple + judge));
		exercise.setMarking("0");
		exercise.setUserId(userId);
		exercise.setStartTime(new Date());
		exercise.setLibraryId(libraryId);
		exercise.setDuration(duration);
		save(exercise);
		
		return exercise;
	}
	
	/**
	 * 开始练习，为该练习准备试题
	 * @param exercise
	 * @param single
	 * @param multiple
	 * @param judge
	 * @return
	 * @throws CRUDException
	 */
	public List<QuestionVO> start(Exercise exercise, int single, int multiple,
			int judge) throws CRUDException {
		List<QuestionVO> lsReturns = new ArrayList<>();
		
		Map<String, Integer> mapQuestionId2Count = new HashMap<>();
		// 单选题
		mapQuestionId2Count.put(Const.QUESTION_TYPE_ID_SINGLE, single);
		// 多选题
		mapQuestionId2Count.put(Const.QUESTION_TYPE_ID_MULTIPLE, multiple);
		// 判断题
		mapQuestionId2Count.put(Const.QUESTION_TYPE_ID_JUDGE, judge);
		
		// 开始为该试卷随机抽取试题
		for (Entry<String, Integer> entry : mapQuestionId2Count.entrySet()) {
			if(entry.getValue() <= 0) {
				continue;
			}
			Question questionQry = new Question();
			questionQry.setLibraryId(exercise.getLibraryId());
			questionQry.setQuestionTypeId(entry.getKey());
			// 查询该试题类型的在指定题库中的全部试题
			List<QuestionVO> lsQuestions = questionService.findByLibraryIdAndTypeId(questionQry);
			
			Set<String> setQuestionIds = new HashSet<>();
			int index = 0;
			QuestionVO question = null;
			while (setQuestionIds.size() < entry.getValue() && setQuestionIds.size() < lsQuestions.size()) {
				// 向setQuestionIds中随机添加试题ID
				index = (int) (Math.random()*lsQuestions.size());
				question = lsQuestions.get(index);
				if(!setQuestionIds.contains(question.getId())) {
					setQuestionIds.add(question.getId());
					lsReturns.add(question);
				}
			}
		}
		
		List<String> lsQuestionIds = new ArrayList<>();
		// 修改试题类型
		for (QuestionVO question : lsReturns) {
			lsQuestionIds.add(question.getId());
			question.setAnswer(""); // 清空正确答案
			/*if (Const.QUESTION_TYPE_ID_SINGLE.equals(question.getQuestionTypeId())) {
				question.setQuestionTypeId("single"); // 单选题
			} else if (Const.QUESTION_TYPE_ID_MULTIPLE.equals(question.getQuestionTypeId())) {
				question.setQuestionTypeId("multiple"); // 多选题
			} else if (Const.QUESTION_TYPE_ID_JUDGE.equals(question.getQuestionTypeId())) {
				question.setQuestionTypeId("judge"); // 判断题
			}*/
		}
		
		List<QuestionOption> lsOptions = questionOptionMapper.findByQuestionIds(lsQuestionIds);
		Map<String, QuestionVO> mapId2QuestionVO = Method.convertListToMap(lsReturns);
		// 将试题选项与试题关联
		for (QuestionOption questionOption : lsOptions) {
			// 暂时仅控制最大提供5个答案选项,手机端屏幕有限
			if(mapId2QuestionVO.get(questionOption.getQuestionId()).getOptionList().size() < 5) {
				mapId2QuestionVO.get(questionOption.getQuestionId()).getOptionList().add(questionOption);
			}
		}
				
		return lsReturns;
	}
	
	/**
	 * 查询登录用户的历史练习成绩列表，按练习时间倒序排序<br>
	 * remarks字段为题库名称<br>
	 * @param userId
	 * @return
	 * @throws CRUDException
	 */
	public List<Exercise> topMyExercise(String userId) throws CRUDException {
		return exerciseMapper.topMyExercise(userId);
	}
}